//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Linq;

using ProjectBase.Core;

using $prjsn$.Entity;
using $prjsn$.Common;
using $prjsn$.Common.Data;
using $prjsn$.Common.Business;
using $prjsn$.Common.Validation;

namespace $safeprojectname$
{
    /// <summary>
    ///   All Business checks for 'BusinessObject' on CRUD operations
    ///   are managed by: BusinessObjectFacade
    /// </summary>
    public class BusinessObjectFacade<TEntity, TFilter, TDao> : BaseFacade<TEntity, int, TFilter, TDao>
        , IBusinessObjectFacade<TEntity, TFilter>
        where TEntity : BusinessObject, new()
        where TFilter : BusinessObjectFilter, new()
        where TDao : class, IBusinessObjectDao<TEntity, TFilter>
    {
        #region IBaseFacade<T> override - FACTORY METHOD

        /// <summary>
        /// Factory Method pattern.
        /// A central and only point for creating new entity of the type BusinessObject.
        /// </summary>
        public override TEntity CreateNew()
        {
            var entity = new TEntity();

            entity.DateCreated = DateTime.Now;
            entity.DateModified = DateTime.Now;

            entity.IsActive = true;

            // TODO
            entity.CountryCode = string.Empty;

            return entity;
        }

        /// <summary>
        /// Needed for the BaseFacade checks on Update() and Delete().
        /// </summary>
        public override TFilter CreateNewFilter()
        {
            var filter = base.CreateNewFilter();
            // TODO preset filter
            return filter;
        }

        #endregion IBaseFacade<T> override - FACTORY METHOD

        #region override Add, Update

        public override TEntity Add(TEntity entity)
        {
            if (entity.Is())
            {
                // TODO e.g. Validate Address
            }
            return base.Add(entity);
        }

        public override TEntity Update(TEntity entity)
        {
            if (entity.Is())
            {
                // TODO e.g. Validate Address
            }
            return base.Update(entity);
        }

        #endregion override Add, Update

        #region override Delete

        public override void Delete(TEntity entity)
        {
            var filter = CreateNewFilter();
            filter.TakeRows = 1;
            filter.ProjectionList[Str.Common.ID] = null;

            if (!Dao.Find(filter).Any()) // need to check if there is still any
            {
                this.PublishWarning(Str.Messages.EntityNotExists2, entity.IDToDisplay, entity.ToDisplay());
                this.PublishError(Str.Messages.CannotDelete1, entity.ToDisplay());
            }

            // OK
            if (EntityValidator.Validate(entity, ValidateOn.Delete, this)
                && !Messages.ContainsError())
            {
                entity.IsActive = false;
                Dao.Update(entity);
                OnChange();
            }
        }

        #endregion override Delete

        #region override BindFilter

        public override TFilter BindFilter(TFilter filter, IValueContainer valueContainer, string prefix = null, string[] includeProperties = null, string[] excludeProperties = null)
        {
            if (filter.IsNull())
            {
                return filter;
            }
            filter = base.BindFilter(filter, valueContainer, prefix, includeProperties, excludeProperties);

            AdditionalBinder.BindAdditional(filter, valueContainer, MetaDataProvider.GetMetaData(), Binder);

            return filter;
        }

        #endregion override BindFilter

        #region IBusinessObjectFacade

        // TODO any application dependent operations,

        #endregion IBusinessObjectFacade

        #region properties

        public virtual AdditionalBinder<TFilter> AdditionalBinder { protected get; set; }

        #endregion properties
    }
}